Last modification: 19 May, 2020

@EricJCGalvez

# check.packages function: install and load multiple R packages.
# Check to see if packages are installed. Install them if they are not, then load them into the R session.
check.packages <- function(pkg){
    new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
    if (length(new.pkg)) 
        install.packages(new.pkg, dependencies = TRUE)
    sapply(pkg, require, character.only = TRUE, warn.conflicts = FALSE, quietly=TRUE)
}

# Usage example
packages<-c("pcaExplorer", "tidyverse", "DESeq2", "dplyr", 
            "ggthemes", "RColorBrewer", "knitr", "ggpubr", 
            "gplots", "genefilter", "ComplexHeatmap", "circlize", 
            "stringr", "here")

check.packages(packages)
source(file = "../R/prok_rnaseq_funs.R")
## Loading required package: rtracklayer

Set input file paths

Loading Files and defining design = Unsupervised 1

DEseq2 normalization

plotDispEsts

Samples similarity

PCA analysis

Pairwise comparisons

Loop

for(i in unique(exps)) {
## subset function, filtering  and deseq execution
dds_ko10 <- select_dds_pair(x = ddsFull, control = control_con, expcond = i, 
                            minreads = 10, minsamples = 4)
## extract results and rld transformation for PCA
contrast_name <- DESeq2::resultsNames(dds_ko10)[2]
res_exp <- DESeq2::results(dds_ko10, contrast=c("condition", i, control_con))  ## ORDEN matters !!
rld <- DESeq2::rlog(dds_ko10)

## PCAs
##################################################

pcals[[i]] <- pcaExplorer::pcaplot(rld, intgroup = c("condition"), ntop = 1000,
        pcX = 1, pcY = 2, title = contrast_name, text_labels = F,
        ellipse = TRUE, ) + scale_fill_manual(values = c( "#B31B21", "steelblue")) +
        scale_color_manual(values = c( "#B31B21", "steelblue")) 

# pcaplot3d(rld, intgroup = c("condition"),ntop = 1000,
#        pcX = 1, pcY = 2, pcZ = 3)

## hi_loadings top 10 signatures
#################################################

pcaobj <- prcomp(t(assay(rld))) 

pcaloads[[i]]<- hi_loadings_plot(pcaobj, topN = 10) #annotation = annotation

## getting gff features 
#################################################
gene_product_df <- get_genproducts(straingff)

## Top 30 up and 30down geneSig from PCA 

## making rownames as a column in a dataframe
df <- as.data.frame(get_top_pca_genes(pcaobj, topN = 30, whichpc = 1))
df <- data.table::setDT(df, keep.rownames = TRUE)[] 
colnames(df) <-  c("gene_id", "pca_loadings")

gene_df <- as.data.frame(assay(dds_ko10))
gene_df <- data.table::setDT(gene_df, keep.rownames = TRUE)[] 
colnames(gene_df)[1] <- c("gene_id") 

all_genes_norm <- merge(gene_df, gene_product_df, by="gene_id")  %>%
                 select(gene_id, product, 2:ncol(gene_df))

top30_loads[[i]] <- all_genes_norm %>%
                 filter(., gene_id %in% df$gene_id)

##### Plot MA function
###################################
## DEseq
###################################
## mergind results with annotation
diff_express=res_exp
diff_express$GENE <- gene_product_df$GeneID[match(row.names(diff_express),
                                                  row.names(gene_product_df))]
diff_express$Name <- gene_product_df$Name[match(row.names(diff_express),
                                                  row.names(gene_product_df))]

plot_lab <- paste0(i, " -> ", control_con)
color_palette <-  c("#B31B21", "#1465AC", "#f7f7f7")
mals[[i]] <- MA_plot(x = diff_express, color=color_palette, main_lab = plot_lab, gename = "Name")
#import 8 x 9 

## DEseq MAtrix
diff_express_df <- as.data.frame(diff_express) %>%
                 select(GENE, Name, 1:ncol(diff_express))

deseq_mat[[i]] <- diff_express_df
}

############################################################3

PROD-eSPF vs PROD-invitro

PROD-Conv vs PROD-invitro

DEseq data integration

##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## using pre-existing size factors
## estimating dispersions
## found already estimated dispersions, replacing these
## gene-wise dispersion estimates
## mean-dispersion relationship
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## final dispersion estimates
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## fitting model and testing
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## using pre-existing size factors
## estimating dispersions
## found already estimated dispersions, replacing these
## gene-wise dispersion estimates
## mean-dispersion relationship
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## final dispersion estimates
##   Note: levels of factors in the design contain characters other than
##   letters, numbers, '_' and '.'. It is recommended (but not required) to use
##   only letters, numbers, and delimiters '_' or '.', as these are safe characters
##   for column names in R. [This is a message, not an warning or error]
## fitting model and testing

Filter genes with less than 10 reads

fold-change (FC) scatter plot

Genes that differ 2X in log2FoldChange between

Interactive scatter

Top DEseq genes between conditions

## Warning: arrange_() is deprecated. 
## Please use arrange() instead
## 
## The 'programming' vignette or the tidyeval book can help you
## to program with arrange() : https://tidyeval.tidyverse.org
## This warning is displayed once per session.
## this is what the function does
pheatmap:::scale_rows
function (x) 
{
    m = apply(x, 1, mean, na.rm = T)
    s = apply(x, 1, sd, na.rm = T)
    return((x - m)/s)
}
LS0tCnRpdGxlOiAiUk5Bc2VxX1BST0QiCmF1dGhvcjogIkVyaWMgSi5DLiBHYWx2ZXoiCmRhdGU6ICIxMi85LzIwMTkiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0aGVtZTogZmxhdGx5CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBncmFwaGljczogeWVzCiAgICB0b2M6IHllcwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KX19MYXN0IG1vZGlmaWNhdGlvbjpfXyBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYAoKQEVyaWNKQ0dhbHZlegoKPCEtLSBtb3JlIC0tPgoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIyBjaGVjay5wYWNrYWdlcyBmdW5jdGlvbjogaW5zdGFsbCBhbmQgbG9hZCBtdWx0aXBsZSBSIHBhY2thZ2VzLgojIENoZWNrIHRvIHNlZSBpZiBwYWNrYWdlcyBhcmUgaW5zdGFsbGVkLiBJbnN0YWxsIHRoZW0gaWYgdGhleSBhcmUgbm90LCB0aGVuIGxvYWQgdGhlbSBpbnRvIHRoZSBSIHNlc3Npb24uCmNoZWNrLnBhY2thZ2VzIDwtIGZ1bmN0aW9uKHBrZyl7CiAgICBuZXcucGtnIDwtIHBrZ1shKHBrZyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywgIlBhY2thZ2UiXSldCiAgICBpZiAobGVuZ3RoKG5ldy5wa2cpKSAKICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKG5ldy5wa2csIGRlcGVuZGVuY2llcyA9IFRSVUUpCiAgICBzYXBwbHkocGtnLCByZXF1aXJlLCBjaGFyYWN0ZXIub25seSA9IFRSVUUsIHdhcm4uY29uZmxpY3RzID0gRkFMU0UsIHF1aWV0bHk9VFJVRSkKfQoKIyBVc2FnZSBleGFtcGxlCnBhY2thZ2VzPC1jKCJwY2FFeHBsb3JlciIsICJ0aWR5dmVyc2UiLCAiREVTZXEyIiwgImRwbHlyIiwgCiAgICAgICAgICAgICJnZ3RoZW1lcyIsICJSQ29sb3JCcmV3ZXIiLCAia25pdHIiLCAiZ2dwdWJyIiwgCiAgICAgICAgICAgICJncGxvdHMiLCAiZ2VuZWZpbHRlciIsICJDb21wbGV4SGVhdG1hcCIsICJjaXJjbGl6ZSIsIAogICAgICAgICAgICAic3RyaW5nciIsICJoZXJlIikKCmNoZWNrLnBhY2thZ2VzKHBhY2thZ2VzKQpgYGAKCmBgYHtyfQpzb3VyY2UoZmlsZSA9ICIuLi9SL3Byb2tfcm5hc2VxX2Z1bnMuUiIpCmBgYAoKIyMjIyBTZXQgaW5wdXQgZmlsZSBwYXRocwoKYGBge3J9CgojIyBSTkFzZXEgY291bnRzIGFuZCBnZW5vbWUgYW5ub3RhdGlvbiBwYXRoCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpkaXJfY291bnRzIDwtIGhlcmUoImRhdGEvIikKc3RyYWluIDwtIGMoIlBST0QiKQpzdHJhaW5nZmYgPC0gIi4uL2dlbm9tZV9yZWZzL1BST0QvUFJPRF9ub2Zhc3RhLmdmZiIKCiMjIyBzZWxlY3QgcGFpciB3aXNlIGNvbnRyYXN0IAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKY29udHJvbF9jb24gPC0gYygiUFJPRC1pbnZpdHJvIikKZXhwX2NvbjEgPC0gYygiUFJPRC1lU1BGIikKZXhwX2NvbjIgPC0gYygiUFJPRC1Db252IikKCmBgYAoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CgpzYW1wbGVGaWxlcyA8LSBncmVwKHN0cmFpbiwgbGlzdC5maWxlcyhkaXJfY291bnRzKSwgdmFsdWU9VFJVRSkKCnNhbXBsZUNvbmRpdGlvbiA8LSBzdHJpbmdyOjpzdHJfbWF0Y2goc2FtcGxlRmlsZXMsICJfKC4qPykuY291bnRzIikgJT4lCiAgICAgICAgICAgICAgICAgICAgZ3N1YigiKHIuKV8iLCAiIiwuICkKc2FtcGxlQ29uZGl0aW9uIDwtIHNhbXBsZUNvbmRpdGlvblssMl0KCnNhbXBsZVRhYmxlIDwtIGRhdGEuZnJhbWUoc2FtcGxlTmFtZSA9IHNhbXBsZUZpbGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVOYW1lID0gc2FtcGxlRmlsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZGl0aW9uID0gc2FtcGxlQ29uZGl0aW9uKQpzYW1wbGVUYWJsZSRzYW1wbGVOYW1lIDwtIGdzdWIoIi5jb3VudHMiLCAiIiwgc2FtcGxlVGFibGUkc2FtcGxlTmFtZSkKc2FtcGxlVGFibGUKYGBgCgojIyMjIExvYWRpbmcgRmlsZXMgYW5kIGRlZmluaW5nIGRlc2lnbiA9IFVuc3VwZXJ2aXNlZCAxCgojIyBERXNlcTIgbm9ybWFsaXphdGlvbgoKIyMjIE5vcm1fdmFyIGFuZCBmaWx0ZXJpbmcKYGBge3IsIHdhcm5pbmc9RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZGRzSFRTZXEgPC0gREVTZXFEYXRhU2V0RnJvbUhUU2VxQ291bnQoc2FtcGxlVGFibGUgPSBzYW1wbGVUYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0b3J5ID0gIGRpcl9jb3VudHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbj0gfiAxKQpkZHNIVFNlcQpkZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNIVFNlcSkKCmRkcyRjb25kaXRpb248LSByZWxldmVsKGRkcyRjb25kaXRpb24sIHJlZiA9IGNvbnRyb2xfY29uKQoKZGRzRnVsbCA8LSBERVNlcShkZHMpIApyZXMgPC0gcmVzdWx0cyggZGRzRnVsbCApCgpib3hwbG90KGxvZzEwKGFzc2F5cyhkZHNGdWxsKVtbImNvb2tzIl1dKSwgcmFuZ2U9MCwgbGFzPTIpCgpgYGAKCiMjIyBwbG90RGlzcEVzdHMKCmBgYHtyfQpwbG90RGlzcEVzdHMoZGRzRnVsbCkKYGBgCgoKIyMgU2FtcGxlcyBzaW1pbGFyaXR5CiMjIyBIZWF0IG1hcAoKYGBge3J9CnJsZEZ1bGwgPC0gREVTZXEyOjpybG9nKCBkZHNGdWxsICkKI2hlYWQoIGFzc2F5KHJsZCkgKQoKc2FtcGxlRGlzdHMgPC0gZGlzdCggdCggYXNzYXkocmxkRnVsbCkgKSApCiNzYW1wbGVEaXN0cwoKc2FtcGxlRGlzdE1hdHJpeCA8LSBhcy5tYXRyaXgoIHNhbXBsZURpc3RzICkKcm93bmFtZXMoc2FtcGxlRGlzdE1hdHJpeCkgPC0gcGFzdGUoIHJsZEZ1bGwkU2FtcGxlX2xhYnMsCnJsZEZ1bGwkVHJlYXRtZW50LCBzZXA9Ii0iICkKY29sbmFtZXMoc2FtcGxlRGlzdE1hdHJpeCkgPC0gTlVMTAoKY29sb3VycyA9IGNvbG9yUmFtcFBhbGV0dGUoIHJldihicmV3ZXIucGFsKDksICJCbHVlcyIpKSApKDI1NSkKaGVhdG1hcC4yKCBzYW1wbGVEaXN0TWF0cml4LCB0cmFjZT0ibm9uZSIsIGNvbD1jb2xvdXJzLCBsYWJSb3c9IHJsZEZ1bGwkY29uZGl0aW9uLAogICAgICAgICAgIGxhYkNvbD0gcmxkRnVsbCRjb25kaXRpb24sIGNleFJvdyA9IDAuOCwgY2V4Q29sID0gMC44LCBzcnRDb2w9NDUsIG1hcmdpbnMgPWMoNi41LDgpICkKCmBgYAoKCiMjIFBDQSBhbmFseXNpcyAKYGBge3J9CnBjYURhdGEgPC0gcGxvdFBDQShybGRGdWxsLCBpbnRncm91cD1jKCJjb25kaXRpb24iKSwgcmV0dXJuRGF0YT1UUlVFKQpwZXJjZW50VmFyIDwtIHJvdW5kKDEwMCAqIGF0dHIocGNhRGF0YSwgInBlcmNlbnRWYXIiKSkKcCA8LSBnZ3Bsb3QocGNhRGF0YSwgYWVzKFBDMSwgUEMyLCBjb2xvcj1jb25kaXRpb24sIHNoYXBlPWNvbmRpdGlvbikpICsKICBnZW9tX3BvaW50KHNpemU9NiwgYWxwaGE9MC43KSArCiAgc2NhbGVfY29sb3JfZ2RvY3MoKSArCiAgeGxhYihwYXN0ZTAoIlBDMTogIixwZXJjZW50VmFyWzFdLCIlIHZhcmlhbmNlIikpICsKICB5bGFiKHBhc3RlMCgiUEMyOiAiLHBlcmNlbnRWYXJbMl0sIiUgdmFyaWFuY2UiKSkgKyAKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygxOCA6IDIxKSkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siLCBzaXplPTAuMikgKwogICAgICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZT0wLjIpCiBwICsgdGhlbWVfYncoMjApCmBgYAoKCiMjIFBhaXJ3aXNlIGNvbXBhcmlzb25zCgojIyMjIyMjIyMjIyMjIyBMb29wICMjIyMjIyMjIyMjIyMKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgU3Vic2FtcGxpbmcgYSBzcGVjaWZpYyB0cmVhdG1lbnQKCmV4cHMgPC0gYyhleHBfY29uMSwgZXhwX2NvbjIpCgpwY2FscyA8LSBsaXN0KCkKcGNhbG9hZHMgPC0gbGlzdCgpCnRvcDMwX2xvYWRzIDwtIGxpc3QoKQptYWxzIDwtIGxpc3QoKQpkZXNlcV9tYXQgPC0gbGlzdCgpCgojaT1leHBfY29uMQoKI3NvdXJjZSgnfi8uYWN0aXZlLXJzdHVkaW8tZG9jdW1lbnQnKQpgYGAKCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKZm9yKGkgaW4gdW5pcXVlKGV4cHMpKSB7CiMjIHN1YnNldCBmdW5jdGlvbiwgZmlsdGVyaW5nICBhbmQgZGVzZXEgZXhlY3V0aW9uCmRkc19rbzEwIDwtIHNlbGVjdF9kZHNfcGFpcih4ID0gZGRzRnVsbCwgY29udHJvbCA9IGNvbnRyb2xfY29uLCBleHBjb25kID0gaSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5yZWFkcyA9IDEwLCBtaW5zYW1wbGVzID0gNCkKIyMgZXh0cmFjdCByZXN1bHRzIGFuZCBybGQgdHJhbnNmb3JtYXRpb24gZm9yIFBDQQpjb250cmFzdF9uYW1lIDwtIERFU2VxMjo6cmVzdWx0c05hbWVzKGRkc19rbzEwKVsyXQpyZXNfZXhwIDwtIERFU2VxMjo6cmVzdWx0cyhkZHNfa28xMCwgY29udHJhc3Q9YygiY29uZGl0aW9uIiwgaSwgY29udHJvbF9jb24pKSAgIyMgT1JERU4gbWF0dGVycyAhIQpybGQgPC0gREVTZXEyOjpybG9nKGRkc19rbzEwKQoKIyMgUENBcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKcGNhbHNbW2ldXSA8LSBwY2FFeHBsb3Jlcjo6cGNhcGxvdChybGQsIGludGdyb3VwID0gYygiY29uZGl0aW9uIiksIG50b3AgPSAxMDAwLAogICAgICAgIHBjWCA9IDEsIHBjWSA9IDIsIHRpdGxlID0gY29udHJhc3RfbmFtZSwgdGV4dF9sYWJlbHMgPSBGLAogICAgICAgIGVsbGlwc2UgPSBUUlVFLCApICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyggIiNCMzFCMjEiLCAic3RlZWxibHVlIikpICsKICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYyggIiNCMzFCMjEiLCAic3RlZWxibHVlIikpIAoKIyBwY2FwbG90M2QocmxkLCBpbnRncm91cCA9IGMoImNvbmRpdGlvbiIpLG50b3AgPSAxMDAwLAojICAgICAgICBwY1ggPSAxLCBwY1kgPSAyLCBwY1ogPSAzKQoKIyMgaGlfbG9hZGluZ3MgdG9wIDEwIHNpZ25hdHVyZXMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKcGNhb2JqIDwtIHByY29tcCh0KGFzc2F5KHJsZCkpKSAKCnBjYWxvYWRzW1tpXV08LSBoaV9sb2FkaW5nc19wbG90KHBjYW9iaiwgdG9wTiA9IDEwKSAjYW5ub3RhdGlvbiA9IGFubm90YXRpb24KCiMjIGdldHRpbmcgZ2ZmIGZlYXR1cmVzIAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmdlbmVfcHJvZHVjdF9kZiA8LSBnZXRfZ2VucHJvZHVjdHMoc3RyYWluZ2ZmKQoKIyMgVG9wIDMwIHVwIGFuZCAzMGRvd24gZ2VuZVNpZyBmcm9tIFBDQSAKCiMjIG1ha2luZyByb3duYW1lcyBhcyBhIGNvbHVtbiBpbiBhIGRhdGFmcmFtZQpkZiA8LSBhcy5kYXRhLmZyYW1lKGdldF90b3BfcGNhX2dlbmVzKHBjYW9iaiwgdG9wTiA9IDMwLCB3aGljaHBjID0gMSkpCmRmIDwtIGRhdGEudGFibGU6OnNldERUKGRmLCBrZWVwLnJvd25hbWVzID0gVFJVRSlbXSAKY29sbmFtZXMoZGYpIDwtICBjKCJnZW5lX2lkIiwgInBjYV9sb2FkaW5ncyIpCgpnZW5lX2RmIDwtIGFzLmRhdGEuZnJhbWUoYXNzYXkoZGRzX2tvMTApKQpnZW5lX2RmIDwtIGRhdGEudGFibGU6OnNldERUKGdlbmVfZGYsIGtlZXAucm93bmFtZXMgPSBUUlVFKVtdIApjb2xuYW1lcyhnZW5lX2RmKVsxXSA8LSBjKCJnZW5lX2lkIikgCgphbGxfZ2VuZXNfbm9ybSA8LSBtZXJnZShnZW5lX2RmLCBnZW5lX3Byb2R1Y3RfZGYsIGJ5PSJnZW5lX2lkIikgICU+JQogICAgICAgICAgICAgICAgIHNlbGVjdChnZW5lX2lkLCBwcm9kdWN0LCAyOm5jb2woZ2VuZV9kZikpCgp0b3AzMF9sb2Fkc1tbaV1dIDwtIGFsbF9nZW5lc19ub3JtICU+JQogICAgICAgICAgICAgICAgIGZpbHRlciguLCBnZW5lX2lkICVpbiUgZGYkZ2VuZV9pZCkKCiMjIyMjIFBsb3QgTUEgZnVuY3Rpb24KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMgREVzZXEKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMgbWVyZ2luZCByZXN1bHRzIHdpdGggYW5ub3RhdGlvbgpkaWZmX2V4cHJlc3M9cmVzX2V4cApkaWZmX2V4cHJlc3MkR0VORSA8LSBnZW5lX3Byb2R1Y3RfZGYkR2VuZUlEW21hdGNoKHJvdy5uYW1lcyhkaWZmX2V4cHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyhnZW5lX3Byb2R1Y3RfZGYpKV0KZGlmZl9leHByZXNzJE5hbWUgPC0gZ2VuZV9wcm9kdWN0X2RmJE5hbWVbbWF0Y2gocm93Lm5hbWVzKGRpZmZfZXhwcmVzcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzKGdlbmVfcHJvZHVjdF9kZikpXQoKcGxvdF9sYWIgPC0gcGFzdGUwKGksICIgLT4gIiwgY29udHJvbF9jb24pCmNvbG9yX3BhbGV0dGUgPC0gIGMoIiNCMzFCMjEiLCAiIzE0NjVBQyIsICIjZjdmN2Y3IikKbWFsc1tbaV1dIDwtIE1BX3Bsb3QoeCA9IGRpZmZfZXhwcmVzcywgY29sb3I9Y29sb3JfcGFsZXR0ZSwgbWFpbl9sYWIgPSBwbG90X2xhYiwgZ2VuYW1lID0gIk5hbWUiKQojaW1wb3J0IDggeCA5IAoKIyMgREVzZXEgTUF0cml4CmRpZmZfZXhwcmVzc19kZiA8LSBhcy5kYXRhLmZyYW1lKGRpZmZfZXhwcmVzcykgJT4lCiAgICAgICAgICAgICAgICAgc2VsZWN0KEdFTkUsIE5hbWUsIDE6bmNvbChkaWZmX2V4cHJlc3MpKQoKZGVzZXFfbWF0W1tpXV0gPC0gZGlmZl9leHByZXNzX2RmCn0KYGBgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIzMKCiMjIGByIGV4cF9jb24xYCB2cyBgciBjb250cm9sX2NvbmAKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcuYWxpZ249J2NlbnRlcid9CnBjYWxzW1tleHBfY29uMV1dCiNlcG9ydCA0WDYKCnBjYWxvYWRzW1tleHBfY29uMV1dCiNlcG9ydCA0WDQKCkRUOjpkYXRhdGFibGUodG9wMzBfbG9hZHNbW2V4cF9jb24xXV0sIGZpbHRlciA9ICd0b3AnLAogICAgICAgICAgZXh0ZW5zaW9ucyA9ICdCdXR0b25zJywgb3B0aW9ucyA9IGxpc3QoCiAgICAgICAgICAjZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnKSwKICAgICAgICAgIHBhZ2VMZW5ndGggPSAxMCwgYXV0b1dpZHRoID0gVCkKICAgICAgICAgICAgICApCgptYWxzW1tleHBfY29uMV1dCiMgNng2CiNwbG90bHk6OmdncGxvdGx5KG1hbHNbW2V4cF9jb24xXV0pICU+JQojICAgICAgICBwbG90bHk6OmxheW91dChsZWdlbmQgPSBsaXN0KG9yaWVudGF0aW9uID0gJ2gnKSkKCkRUOjpkYXRhdGFibGUoZGVzZXFfbWF0W1tleHBfY29uMV1dLCBmaWx0ZXIgPSAndG9wJywKICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnKSwKICAgICAgICAgIHBhZ2VMZW5ndGggPSA1LCBhdXRvV2lkdGggPSBUKQogICAgICAgICAgICAgICkKYGBgCgoKIyMgYHIgZXhwX2NvbjJgIHZzIGByIGNvbnRyb2xfY29uYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcuYWxpZ249J2NlbnRlcid9CnBjYWxzW1tleHBfY29uMl1dCgpwY2Fsb2Fkc1tbZXhwX2NvbjJdXQoKRFQ6OmRhdGF0YWJsZSh0b3AzMF9sb2Fkc1tbZXhwX2NvbjJdXSwgZmlsdGVyID0gJ3RvcCcsCiAgICAgICAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLCBvcHRpb25zID0gbGlzdCgKICAgICAgICAgICNkb20gPSAnQmZydGlwJywKICAgICAgICAgIGJ1dHRvbnMgPSBjKCdjb3B5JywgJ2NzdicsICdleGNlbCcpLAogICAgICAgICAgcGFnZUxlbmd0aCA9IDEwLCBhdXRvV2lkdGggPSBUKQogICAgICAgICAgICAgICkKCm1hbHNbW2V4cF9jb24yXV0KCkRUOjpkYXRhdGFibGUoZGVzZXFfbWF0W1tleHBfY29uMl1dLCBmaWx0ZXIgPSAndG9wJywKICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnKSwKICAgICAgICAgIHBhZ2VMZW5ndGggPSA1LCBhdXRvV2lkdGggPSBUKQogICAgICAgICAgICAgICkKYGBgCgojIyBERXNlcSBkYXRhIGludGVncmF0aW9uCgpgYGB7cn0KCmRlc2VxcmVzX2xzIDwtIGxpc3QoKQoKZm9yKGkgaW4gdW5pcXVlKGV4cHMpKSB7CiMjIHN1YnNldCBmdW5jdGlvbiwgZmlsdGVyaW5nICBhbmQgZGVzZXEgZXhlY3V0aW9uCmRkc19rbzEwIDwtIHNlbGVjdF9kZHNfcGFpcih4ID0gZGRzRnVsbCwgY29udHJvbCA9IGNvbnRyb2xfY29uLCBleHBjb25kID0gaSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5yZWFkcyA9ICwgbWluc2FtcGxlcyA9MCkKIyMgZXh0cmFjdCByZXN1bHRzIGFuZCBybGQgdHJhbnNmb3JtYXRpb24gZm9yIFBDQQpjb250cmFzdF9uYW1lIDwtIERFU2VxMjo6cmVzdWx0c05hbWVzKGRkc19rbzEwKVsyXQpyZXNfZXhwIDwtIERFU2VxMjo6cmVzdWx0cyhkZHNfa28xMCwgY29udHJhc3Q9YygiY29uZGl0aW9uIiwgaSwgY29udHJvbF9jb24pKSAgIyMgT1JERU4gbWF0dGVycyAhIQpkZXNlcXJlc19sc1tbaV1dIDwtIGFzLmRhdGEuZnJhbWUocmVzX2V4cCkKfQoKYGBgCgoKIyMjIyBGaWx0ZXIgZ2VuZXMgd2l0aCBsZXNzIHRoYW4gMTAgcmVhZHMKIyMjIyBJZGVudGlmeSBnZW5lcyB3aXRoIEZDID4gMiBmYyBhbmQgbGFiZWwgdGhlbSAKYGBge3J9CmR0IDwtIGJpbmRfY29scyhkZXNlcXJlc19scykKZHRfZiA8LSBkdCAlPiUgCiAgICAgICAgbXV0YXRlKC4sIE1lYW5FeHA9YWJzKC4kYmFzZU1lYW4tLiRiYXNlTWVhbjEvMiksIAogICAgICAgICAgICAgICAgICBnZW5lX2lkPSByb3duYW1lcyhkZXNlcXJlc19sc1tbMV1dKSkgJT4lCiAgICAgICAgZmlsdGVyKC4sIE1lYW5FeHAgPj0gMTApICU+JQogICAgICAgIGFzLmRhdGEuZnJhbWUoKQoKZHRfZiA8LSBtZXJnZShkdF9mLCBnZW5lX3Byb2R1Y3RfZGYsIGJ5PSJnZW5lX2lkIikgICU+JQogICAgICAgICAgICAgICAgIHNlbGVjdChnZW5lX2lkLCBOYW1lLCBwcm9kdWN0LCBNZWFuRXhwLCAxOm5jb2woZ2VuZV9kZikpCgpkdF9mIDwtIGR0X2YgJT4lCiAgbXV0YXRlKEhpZ2hsaWdodHM9aWZlbHNlKGFicyhkdF9mJGxvZzJGb2xkQ2hhbmdlIC0gZHRfZiRsb2cyRm9sZENoYW5nZTEpID49IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uocm93TWVhbnMoZHRfZltjKCJsb2cyRm9sZENoYW5nZSIsICJsb2cyRm9sZENoYW5nZTEiKV0pID49IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRkFMU0UpKSkKCmBgYAoKCiMjIGZvbGQtY2hhbmdlIChGQykgIHNjYXR0ZXIgcGxvdAojIyMgR2VuZXMgdGhhdCBkaWZmZXIgMlggaW4gbG9nMkZvbGRDaGFuZ2UgYmV0d2VlbiAgCiMjIyAgYHIgZXhwX2NvbjFgIGFuZCBgciBleHBfY29uMmAgIm5vcm1hbGl6ZWQiIGJ5IGByIGNvbnRyb2xfY29uYAojIyMjIFVzaW5nIGdlbmUgTmFtZXMKYGBge3IsIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTEyfQpwIDwtIGdncGxvdChkdF9mLCBhZXMoeCA9IGxvZzJGb2xkQ2hhbmdlMSwgeSA9IGxvZzJGb2xkQ2hhbmdlLCBsYWJlbD1OYW1lLAogICAgICAgICAgICAgICAgIHNpemUgPSBNZWFuRXhwKSApICsKICAgICAgZ2VvbV9wb2ludChjb2xvciA9IGlmZWxzZShhYnMoZHRfZiRsb2cyRm9sZENoYW5nZSAtIGR0X2YkbG9nMkZvbGRDaGFuZ2UxKSA+PSAyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShyb3dNZWFucyhkdF9mW2MoImxvZzJGb2xkQ2hhbmdlIiwgImxvZzJGb2xkQ2hhbmdlMSIpXSkgPj0gMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJsdWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibGFjayIpKSwgYWxwaGE9IDAuMykgKwogICAgICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yID0gImJsdWUiLCBzaXplPTAuMikgKwogICAgICAgICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yID0gImJsdWUiLCBzaXplPTAuMikgKwogICAgICAgICAgI3hsaW0oLTEwLCBOQSkgKwogICAgICAgICAgI3lsaW0oLTEwLCBOQSkgKwogICAgICAgICAgeGxhYigiRkMoZVNQRiB2cyBpbnZpdHJvKSIpICsgCiAgICAgICAgICB5bGFiKCJGQyhDb252IHZzIGludml0cm8pIikgKyB0aGVtZV9idygyNCkKICAKCnAgKyBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGR0X2ZbZHRfZiRIaWdobGlnaHRzLCBdLCAKICAgICAgICAgICAgYWVzKGxhYmVsID0gTmFtZSksIHNpemUgPSAzLjUsIGJveC5wYWRkaW5nID0gdW5pdCgwLjEsIAogICAgICAgICAgICAgICAgImxpbmVzIiksIHBvaW50LnBhZGRpbmcgPSB1bml0KDAuMSwgImxpbmVzIiksIAogICAgICAgICAgICBzZWdtZW50LnNpemUgPSAwLjUpCgpgYGAKCiMjIyBJbnRlcmFjdGl2ZSBzY2F0dGVyCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04fQoKcCA8LSBnZ3Bsb3QoZHRfZiwgYWVzKHggPSBsb2cyRm9sZENoYW5nZTEsIHkgPSBsb2cyRm9sZENoYW5nZSwgbGFiZWw9Z2VuZV9pZCwKICAgICAgICAgICAgICAgICBzaXplID0gTWVhbkV4cCkgKSArCiAgICAgIGdlb21fcG9pbnQoY29sb3IgPSBpZmVsc2UoYWJzKGR0X2YkbG9nMkZvbGRDaGFuZ2UgLSBkdF9mJGxvZzJGb2xkQ2hhbmdlMSkgPj0gMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2Uocm93TWVhbnMoZHRfZltjKCJsb2cyRm9sZENoYW5nZSIsICJsb2cyRm9sZENoYW5nZTEiKV0pID49IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJibHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmxhY2siKSksIGFscGhhPSAwLjMpICsKICAgICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJibHVlIiwgc2l6ZT0wLjIpICsKICAgICAgICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJibHVlIiwgc2l6ZT0wLjIpICsKICAgICAgICAgICN4bGltKC0xMCwgTkEpICsKICAgICAgICAgICN5bGltKC0xMCwgTkEpICsKICAgICAgICAgIHhsYWIoIkZDKGVTUEYgdnMgaW52aXRybykiKSArIAogICAgICAgICAgeWxhYigiU0xSKENvbnYgdnMgaW52aXRybykiKSArIHRoZW1lX2J3KDI0KQoKcGxvdGx5OjpnZ3Bsb3RseShwKQpgYGAKCgpgYGB7cn0KRFQ6OmRhdGF0YWJsZShkdF9mLCBmaWx0ZXIgPSAndG9wJywKICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnKSwKICAgICAgICAgIHBhZ2VMZW5ndGggPSA1LCBhdXRvV2lkdGggPSBUKQogICAgICAgICAgICAgICkKYGBgCgojIyBUb3AgREVzZXEgZ2VuZXMgYmV0d2VlbiBjb25kaXRpb25zCgpgYGB7cn0KIyMjIyByZWNhcGl0dWxhdGUgYWxsIHJlc3VsdHMgZGF0YWZybWUKcmVzX3RheCA8LSBtZXJnZShhcy5kYXRhLmZyYW1lKHJlcyksIGFzLmRhdGEuZnJhbWUoY291bnRzKGRkc0Z1bGwsIG5vcm1hbGl6ZWQ9VCkpLCBieT0ncm93Lm5hbWVzJywgc29ydD1GKQpuYW1lcyhyZXNfdGF4KVsxXSA8LSAnZ2VuZV9pZCcKcmVzX3RheCROYW1lPWdlbmVfcHJvZHVjdF9kZiROYW1lW21hdGNoKHJlc190YXgkZ2VuZV9pZCwgZ2VuZV9wcm9kdWN0X2RmJGdlbmVfaWQpXQoKYGBgCgoKCmBgYHtyfQoKZHQxIDwtIGRlc2VxX21hdFtbZXhwX2NvbjFdXQpkdDIgPC0gZGVzZXFfbWF0W1tleHBfY29uMl1dCmR0MyA8LSByZXNfdGF4CgpnZW5lc19oZWF0bWFwIDwtIGdldF9oZWF0bWFwX0lEcyhkdDEsIGR0MiwgZHQzLCB0b3BOYiA9IDI1KQpgYGAKCgoKYGBge30KIyMgdGhpcyBpcyB3aGF0IHRoZSBmdW5jdGlvbiBkb2VzCnBoZWF0bWFwOjo6c2NhbGVfcm93cwpmdW5jdGlvbiAoeCkgCnsKICAgIG0gPSBhcHBseSh4LCAxLCBtZWFuLCBuYS5ybSA9IFQpCiAgICBzID0gYXBwbHkoeCwgMSwgc2QsIG5hLnJtID0gVCkKICAgIHJldHVybigoeCAtIG0pL3MpCn0KYGBgCgojIyMgSGVhdCBtYXAgdG9wIDI1IGFubm90YXRlZCBnZW5lcyAKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTZ9CgptYXQgPC0gcGhlYXRtYXA6OjpzY2FsZV9yb3dzKGFzc2F5KHJsZEZ1bGwpW2dlbmVzX2hlYXRtYXAkZ2VuZV9pZCwgXSkKdHlwZSA8LSBzYW1wbGVDb25kaXRpb24KaGEgPSBIZWF0bWFwQW5ub3RhdGlvbihkZiA9IGRhdGEuZnJhbWUodHlwZSA9IHNhbXBsZUNvbmRpdGlvbiksIG5hbWUgPSAiRXhwZXJpbWVudCIpCgoKY29sX2Z1biA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMoLTIsIDAsIDIpLCBjKCIjOTJjNWRlIiwgIiNmZmZmZTUiLCAiI2IyMTgyYiIpKQoKQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAobWF0LCBuYW1lID0gImV4cHJlc3Npb24iLCB0b3BfYW5ub3RhdGlvbiA9IGhhLCBjb2x1bW5fc3BsaXQgPSB0eXBlLCBjb2wgPSBjb2xfZnVuLAogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCBzaG93X3Jvd19uYW1lcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICBzaG93X2NvbHVtbl9uYW1lcyA9IEZBTFNFLCBib3JkZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICByb3dfdGl0bGVfcm90ID0gMCwgcm93X3RpdGxlX2dwID0gZ3Bhcihmb250c2l6ZSA9IDgpKSArCiAgICAgICAgICAgICAgICByb3dBbm5vdGF0aW9uKGxpbmsgPSBhbm5vX21hcmsoYXQgPSB3aGljaCghaXMubmEoZ2VuZXNfaGVhdG1hcCROYW1lKSksIAogICAgICAgICAgICAgICAgbGFiZWxzID0gZ2VuZXNfaGVhdG1hcCROYW1lWyB3aGljaCghaXMubmEoZ2VuZXNfaGVhdG1hcCROYW1lKSldLCAKICAgICAgICAgICAgICAgIGxhYmVsc19ncCA9IGdwYXIoZm9udHNpemUgPSA4KSwgcGFkZGluZyA9IDAuNSkpIApgYGAKCg==